package org.heima.core;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SqlSession {

    private SqlSessionFactory factory;

    public SqlSession(SqlSessionFactory sqlSessionFactory) {
        this.factory = sqlSessionFactory;
    }

    public int insert(String sqlId,Object object){
        int count = 0;
        try {
            Connection connection = factory.getTransaction().getConnection();
            //insert into xx(a,b)values (#{a},#{b})
            String sql = factory.getMapperStatementMap().get(sqlId).getSql();
            //insert into xx(a,b)values (?,?)
            String newSql = sql.replaceAll("(#|\\$)\\{.*?\\}", "?");
            PreparedStatement preparedStatement = connection.prepareStatement(newSql);
            //传参
            int index = 1;
            String regex = "#\\{(.*?)}";
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(sql);
            while (matcher.find()) {
//                System.out.println(index);
                String propertyName = matcher.group(1);
//                System.out.println(propertyName);// group(1) 因为我们只关心第一个捕获组的内容
                String getMethodName = "get" + propertyName.toUpperCase().charAt(0) +
                        propertyName.substring(1);//getId
                Method getMethod = object.getClass().getDeclaredMethod(getMethodName);
                Object propertyValue = getMethod.invoke(object);
                preparedStatement.setString(index,propertyValue.toString());
                index++;
            }

            count = preparedStatement.executeUpdate();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return count;
    }

    public Object selectOne(String sqlId,Object param){
        Object object = null;
        try {
            Connection connection = factory.getTransaction().getConnection();
            String sql = factory.getMapperStatementMap().get(sqlId).getSql();
            String resultType = factory.getMapperStatementMap().get(sqlId).getResultType();
            String newSql = sql.replaceAll("(#|\\$)\\{.*?\\}", "?");
            PreparedStatement preparedStatement = connection.prepareStatement(newSql);
            preparedStatement.setString(1,param.toString());
            ResultSet resultSet = preparedStatement.executeQuery();

            if (resultSet.next()) {
                Class<?> resultTypeClass = Class.forName(resultType);
                object = resultTypeClass.newInstance();
                ResultSetMetaData rsmd = resultSet.getMetaData();
                int columnCount = rsmd.getColumnCount();
                for (int i = 0; i < columnCount; i++) {
                    String propertyName = rsmd.getColumnName(i+1);
                    String setMethodName = "set" + propertyName.toUpperCase().charAt(0) +
                            propertyName.substring(1);//setId
                    Field field = resultTypeClass.getDeclaredField(propertyName);
                    Class<?> type = field.getType();
                    Method setMethod = null;
                    if (type==String.class){
                        setMethod = resultTypeClass.getDeclaredMethod(setMethodName, String.class);
                        setMethod.invoke(object,resultSet.getString(propertyName));
                    } else if (type == Long.class) {
                        setMethod = resultTypeClass.getDeclaredMethod(setMethodName, Long.class);
                        setMethod.invoke(object,resultSet.getLong(propertyName));
                    } else if (type == Double.class) {
                        setMethod = resultTypeClass.getDeclaredMethod(setMethodName, Double.class);
                        setMethod.invoke(object,resultSet.getDouble(propertyName));
                    }

                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return object;
    }

    public void commit(){
        factory.getTransaction().commit();
    }

    public void rollback(){
        factory.getTransaction().rollback();
    }

    public void close(){
        factory.getTransaction().close();
    }
}
